package pl.edu.agh.transstat.parsing;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import pl.edu.agh.transstat.simulation.Configuration;

public class SimulationConfigurationParser extends DefaultHandler {

	private Map<String, Configuration> confList;
	private List<String> paths;
	private String nameTmp;
	private boolean isName = false;
	private Configuration confTmp;

	public SimulationConfigurationParser(String rootPath) {
		this.confList = new HashMap<String, Configuration>();
		getPaths(rootPath, "xml");
		for (String p : paths) {
			parseDocument(p);
		}
	}

	private void parseDocument(String path) {
		// get a factory
		SAXParserFactory spf = SAXParserFactory.newInstance();
		try {
			File file = new File(path);
			InputStream inputStream = new FileInputStream(file);
			Reader reader = new InputStreamReader(inputStream, "UTF-8");

			InputSource is = new InputSource(reader);
			is.setEncoding("UTF-8");
			// get a new instance of parser
			SAXParser sp = spf.newSAXParser();
			// parse the file and also register this class for call backs
			sp.parse(is, this);

		} catch (SAXException se) {
			se.printStackTrace();
		} catch (ParserConfigurationException pce) {
			pce.printStackTrace();
		} catch (IOException ie) {
			ie.printStackTrace();
		}
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		if (qName.equalsIgnoreCase(ConfigurationTags.test)) {
			confTmp = new Configuration();
		}
		if (qName.equalsIgnoreCase(ConfigurationTags.commissions)) {
			if (attributes.getValue(ConfigurationTags.dynamic) != null) {
				confTmp.setDynamic(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.dynamic)));
			}
			if (attributes.getValue(ConfigurationTags.packageSending) != null) {
				confTmp.setPackageSending(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.packageSending)));
			}
			if (attributes.getValue(ConfigurationTags.choosingByCost) != null) {
				confTmp.setChoosingByCost(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.choosingByCost)));
			}
			if (attributes.getValue(ConfigurationTags.STDepth) != null) {
				confTmp.setSTDepth(Integer.parseInt(attributes
						.getValue(ConfigurationTags.STDepth)));
			}
			if (attributes.getValue(ConfigurationTags.worstCommission) != null) {
				confTmp.setWorstCommission(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.worstCommission)));
			}
			if (attributes.getValue(ConfigurationTags.algorithm) != null) {
				confTmp.setAlgorithm(attributes
						.getValue(ConfigurationTags.algorithm));
			}
			if (attributes.getValue(ConfigurationTags.autoConfig) != null) {
				confTmp.setAutoConfig(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.autoConfig)));
			}
			if (attributes.getValue(ConfigurationTags.firstComplexSTResultOnly) != null) {
				confTmp.setFirstComplexSTResultOnly(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.firstComplexSTResultOnly)));
			}
		}

		if (qName.equalsIgnoreCase(ConfigurationTags.roadGraph)) {
			if (attributes.getValue(ConfigurationTags.trackFinder) != null) {
				confTmp.setTrackFinder(attributes
						.getValue(ConfigurationTags.trackFinder));
			}
			if (attributes.getValue(ConfigurationTags.ST) != null) {
				confTmp.setST(Boolean.parseBoolean(attributes
						.getValue(ConfigurationTags.ST)));
			}
			if (attributes.getValue(ConfigurationTags.changeTime) != null) {
				confTmp.setChangeTime(attributes
						.getValue(ConfigurationTags.changeTime));
			}
			if (attributes.getValue(ConfigurationTags.notificationTime) != null) {
				confTmp.setNotificationTime(Integer.parseInt(attributes
						.getValue(ConfigurationTags.notificationTime)));
			}
			if (attributes.getValue(ConfigurationTags.predictor) != null) {
				confTmp.setPredictor(attributes
						.getValue(ConfigurationTags.predictor));
			}
		}

		if (qName.equalsIgnoreCase(ConfigurationTags.results)) {
			isName = true;
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		if (qName.equals(ConfigurationTags.test)) {
			confList.put(nameTmp, confTmp);
		}

	}

	@Override
	public void characters(char ch[], int start, int length) throws SAXException {
		if(isName){
			String temp[] = (new String(ch, start, length)).split("/");
			nameTmp = temp[temp.length-1];
			isName = false;
		}
	}
	
	public Map<String, Configuration> getData() {
		return confList;
	}

	private void getPaths(String in, String end) {
		paths = new ArrayList<String>();
		File root = new File(in);
		getFiles(root, end);
	}

	private void getFiles(File file, String end) {
		for (File f : file.listFiles()) {
			if (f.isDirectory()) {
				getFiles(f, end);
			} else {
				String temp[] = f.getName().split("\\.");
				if (temp[temp.length - 1].equals(end)) {
					paths.add(f.getPath());
				}
			}
		}

	}

}
